<template>
  <div class="init-container">
    <div class="mask-container" v-if="isMask"></div>
    <div class="production-overview" ref="productionOverview">
      <o-context-menu
        ref="contextMenu"
        v-model="contextMenuVisible"
        :list="menuItems"
        :displayPosition="menuPosition"
        @on-select="handleMenuSelect"
      />
      <div class="header">
        <template v-for="(info, idx) of lineHeaderInfo">
          <div
            class="install-info info-column"
            :key="idx"
            v-if="info.column.key === 'task'"
          >
            <div class="info-title">{{ info.column.title }}</div>
            <div class="task-info">
              <div
                class="task-info-item std-border"
                v-for="(task, idxx) of lineHeaderInfo[idx].cases"
                :key="idxx"
              >
                <div class="task-info-item-title">{{ task.title }}</div>
                <div class="task-info-item-value">
                  <span>{{ task.value }}</span>
                </div>
              </div>
            </div>
          </div>

          <div
            class="alert-column"
            :key="idx"
            v-else-if="info.column.key === 'alert'"
          >
            <div class="alert-title">
              <span>{{ info.column.title }}</span>
              <!-- <Button size="small" type="warning" @click="jumptoAlarmQuery()"
                >报警查询</Button
              > -->
            </div>
            <div class="alert-info">
              <div class="alert-content">
                <div
                  class="alert-info-item"
                  v-for="(alert, idxx) of lineHeaderInfo[idx].cases"
                  :key="idxx"
                  @contextmenu.prevent="showContextMenu($event, alert)"
                >
                  {{ alert.content }}
                </div>
              </div>
            </div>
          </div>

          <div class="install-info info-column" :key="idx" v-else>
            <div class="info-title">{{ info.column.title }}</div>
            <div class="info-content">
              <div
                class="info-content-item"
                v-for="(cass, idxx) in lineHeaderInfo[idx].cases"
                :key="idxx"
                :title="cass.value"
              >
                <div v-if="cass.type === 'text'">
                  <span class="info-content-item-title">{{ cass.title }}:</span>
                  <span class="info-content-item-value">
                    {{ cass.value }}
                  </span>
                </div>
                <div v-else>
                  {{ cass.value ? cass.trueText : cass.falseText }}
                </div>
              </div>
            </div>
          </div>
        </template>
      </div>

      <!-- 行车运动部分 -->
      <div class="main" ref="main">
        <plating-line
          :config="lineConfig"
          :cavans-height="cavansHeight"
          @update-tank="handleUpdateTank"
          ref="platingLine"
        />
      </div>

      <!-- 产线状态信息及操作 -->
      <control-panels
        :craneControlConfig="craneControlConfig"
        :autoButtonPanel="autoButtonPanel"
        @show-modal="specifyRunningSteps"
      />
    </div>
    <o-modal
      v-model="modalVisible"
      title="指定运行步骤"
      :size="[400, 350]"
      :mask="true"
      :tap-close="false"
      :show-footer="false"
    >
      <Form
        :label-width="115"
        slot="content"
        class="modal-content"
        :inline="true"
        label-position="left"
      >
        <div class="modal-left">
          <template
            v-for="item of formConfig.filter(it => it.type === 'button')"
          >
            <Button
              :key="item.key"
              @click="modalBtnClick(item)"
              size="large"
              :type="item.btnType"
              :disabled="item.disabled"
              >{{ item.title }}</Button
            >
          </template>
        </div>
        <div class="modal-right">
          <template
            v-for="item of formConfig.filter(it => it.type === 'input')"
          >
            <FormItem :label="item.title" :key="item.key">
              <InputNumber
                size="large"
                v-model="item.value"
                :readonly="item.disabled"
                @on-blur="modalInputChange(item)"
              />
            </FormItem>
          </template>
        </div>
      </Form>
    </o-modal>
  </div>
</template>

<script lang="ts">
import oModal from '@/components/base/modal/o-modal/index.vue';
import oContextMenu from '@/components/base/menu/o-context-menu/index.vue';
import PlatingLine from './PlatingLine.vue';
import ControlPanels from './ControlPanels.vue';
import {
  I_cmd,
  N_cStph,
  T_cmd,
  T_srv,
  Tsrv,
  ifs,
  vue,
  lineHeaderConfig,
  lineMainConfig,
  formConfig,
  craneControlConfig,
  autoButtonPanel
} from './config';

type CollisionWarningEvent = N_cStph.CollisionWarningEvent;
type ProductionLineConfig = N_cStph.ProductionLineConfig;
@T_srv.comp({
  components: {
    PlatingLine,
    oModal,
    oContextMenu,
    ControlPanels
  }
})
// Surface treatment process homepage
export default class cStph extends vue {
  /* 父组件compBoxInfo */
  @T_srv.prop({
    required: false,
    type: Object,
    default: null
  })
  compBoxInfo: ifs.I_compBoxInfo;

  @T_srv.inject({ default: () => {} }) addTabFunc;

  /* 组件名 */
  private name: string = 'cStph';

  private G_compName: string = this.name;

  /* 组件箱信息对象 */
  private GT_compBoxInfo: ifs.I_compBoxInfo;

  /* 组件箱对象 */
  private GT_compBox: ifs.I_compBox;

  /* 组件箱识别ID */
  private G_compID: string;

  /* 指挥部 */
  private GT_command: I_cmd = new T_cmd();

  /* 遮罩 */
  public isMask: boolean = false;

  private modalVisible: boolean = false;

  public lineHeaderInfo = lineHeaderConfig();

  public craneControlConfig: N_cStph.craneControlConfig[] = craneControlConfig();

  public autoButtonPanel: N_cStph.autoBtn[] = autoButtonPanel();

  public platingLine: PlatingLine;

  public lineConfig: ProductionLineConfig = lineMainConfig();

  private cavansHeight: number = 400;

  private formConfig: N_cStph.formInfo[] = formConfig();

  // 启动按钮间隔定时器
  private timer: any;

  private menuItems = [
    { name: 'acknowledge', title: '应答报警' },
    { name: 'reset', title: '复位报警' },
    { name: 'query', title: '跳转报警查询' },
    { name: 'control', title: '跳转设备控制' }
  ];

  // 菜单显示状态
  private contextMenuVisible = false;

  // 菜单位置
  private menuPosition = { clientX: 100, clientY: 100 };

  created() {
    // 如果父组件没有传参，那就产生一个
    this.GT_compBoxInfo = Tsrv.getCompInfo(this.compBoxInfo);
    this.G_compID = this.GT_compBoxInfo.compID;
    this.GT_compBox = this.GT_compBoxInfo.TcompBox;
    this.GT_command.init(this, this.GT_compBoxInfo);
  }

  mounted() {
    this.platingLine = this.$refs.platingLine as PlatingLine;

    // 监听碰撞警告事件
    this.platingLine.$on('collision-warning', this.handleCollisionWarning);

    this.receiveEvent();
    this.GT_command.getTaskInfo();

    this.cavansHeight = (this.$refs.main as HTMLElement).clientHeight;
    document.addEventListener('click', this.handleOutsideClick);

    Tsrv.store.dispatch('initPlcData');

    this.GT_command.startTask();
  }

  beforeDestroy() {
    this.GT_command.stopTask();
    const platingLine = this.$refs.platingLine as PlatingLine;
    platingLine.$off('collision-warning', this.handleCollisionWarning);
    this.$bus.$off('UPDATE_TASK_INFO');
    this.$bus.$off('__PLC_CONNSTATE__');
    document.removeEventListener('click', this.handleOutsideClick);
  }

  destroyed() {
    /* 注册组件销毁 */
    this.GT_compBox.removeCompMergeName(this.G_compID, this.G_compName);

    /* 如果父组件传入的compBoxInfo则删除本文件产生的引用,反之是本组件产生的ID统一删除 */
    if (Tsrv.utils.isEmpty(this.compBoxInfo)) {
      this.GT_compBox.removeCompsWithCompID(this.G_compID);
    } else {
      this.GT_compBox.removeCompsMergeName(this.G_compID, [
        `'${this.G_compName}'`
      ]);
    }
  }

  /* 设置组件整体遮罩 */
  public setMask(p: boolean) {
    this.isMask = p;
  }

  public getMask(p: boolean): boolean {
    return this.isMask;
  }

  // 处理碰撞警告
  private handleCollisionWarning(warning: CollisionWarningEvent): void {
    console.warn(
      `警告：行车 ${warning.craneId} 和行车 ${warning.otherCraneId} ` +
        `之间的距离为 ${warning.distance}，小于安全距离！`
    );
    // 这里可以添加声音警报、显示警告消息等
  }

  // 接收事件
  private receiveEvent() {
    // 更新任务信息
    this.$bus.$on('UPDATE_TASK_INFO', (info: N_cStph.I_taskInfo) => {
      this.updateTaskInfo(info);
    });

    this.$bus.$on(
      '__PLC_CONNSTATE__',
      (data: { connState: boolean; ecBoxName: string }) => {
        if (data.ecBoxName === 'mianyang') {
          if (data.connState) {
            if (!this.GT_command.isOpenTask) {
              this.GT_command.startTask();
            }
          } else {
            this.GT_command.stopTask();
          }
        }
      }
    );
  }

  // 匹配报警槽,并返回报警槽的id
  private matchAlarmSlot(alarmInfo: N_cStph.alarmInfo[]): number[] {
    const result = []; // 存储所有匹配到的槽号
    const regex = /(\d+槽)/; // 正则表达式匹配数字加槽
    for (const alarm of alarmInfo) {
      const match = alarm.equipFunName.match(regex);
      if (match) {
        const slotNumber = match[0].replace('槽', ''); // 提取出数字部分
        result.push(slotNumber);
      }
    }
    return result;
  }

  // 更新任务信息
  public updateTaskInfo(info: N_cStph.I_taskInfo) {
    this.lineHeaderInfo[1].cases[0].value = info.doneCount;
    this.lineHeaderInfo[1].cases[1].value = info.workCount;
    this.lineHeaderInfo[1].cases[2].value = info.waitCount;
  }

  /* 指定运行步 */
  private specifyRunningSteps() {
    this.modalVisible = true;
  }

  private jumptoAlarmQuery(btn: any) {
    this.$store
      .dispatch('getLayoutConfigAsync', {
        funid: null,
        field: 'cAlarmQuery',
        type: 'custom'
      })
      .then((res: any) => {
        if (res) {
          this.addTabFunc('cAlarmQuery');
        }
      });
  }

  private modalBtnClick(it: N_cStph.formInfo) {
    const data = [{ ecDetCode: it.ecCode, value: 'true' }];
    this.GT_command.writePlcData(data, true).then(success => {
      if (success) {
        this.$Message.success(`${it.title}成功`);
        const codes = [];
        this.formConfig.forEach(i => {
          codes.push(i.ecCode);
        });
        Tsrv.readPlcData(codes).then(res => {
          if (typeof res === 'boolean') return;
          this.formConfig.forEach(i => {
            i.value = res[i.ecCode].v;
          });
        });
      }
    });
  }

  private modalInputChange(it: N_cStph.formInfo) {
    if (!Tsrv.noValue(it.value)) {
      switch (it.key) {
        case 'queryNum':
          this.inputChange(it, 'stepOut');
          break;
        case 'targetStepNum':
          this.inputChange(it, 'stepWrite');
          break;
        default:
          this.inputChange(it);
          break;
      }
    }
  }

  private inputChange(it: N_cStph.formInfo, btnName?: string) {
    const data = [
      {
        ecDetCode: it.ecCode,
        value: it.value.toString()
      }
    ];
    this.GT_command.writePlcData(data).then(success => {
      if (success) {
        if (!Tsrv.noValue(btnName)) {
          // 将序号取出按钮禁用状态置为false
          this.formConfig.forEach(item => {
            if (item.key === btnName) item.disabled = false;
          });
        }
      }
    });
  }

  // 右键菜单相关逻辑

  private selectedAlert: N_cStph.alarmInfo;

  // 显示右键菜单
  private showContextMenu(event: MouseEvent, alert: any) {
    event.preventDefault();
    this.selectedAlert = alert;
    this.menuPosition = {
      clientX: event.clientX - 60,
      clientY: event.clientY - 70
    };
    this.contextMenuVisible = true;
  }

  private handleOutsideClick(event) {
    // 如果不在右键菜单的区域内，则隐藏右键菜单
    const contextMenu = (this.$refs.contextMenu as Vue).$el;
    if (contextMenu && !contextMenu.contains(event.target)) {
      this.contextMenuVisible = false;
    }
  }

  private hideContextMenu() {
    this.contextMenuVisible = false;
  }

  private handleMenuSelect(action: string) {
    this.hideContextMenu();
    switch (action) {
      case 'acknowledge':
        this.acknowledgeAlert(this.selectedAlert);
        break;
      case 'reset':
        this.resetAlert(this.selectedAlert);
        break;
      case 'query':
        this.jumptoAlarmQuery(this.selectedAlert);
        break;
      case 'control':
        this.jumpToDeviceControl();
        break;
      default:
        break;
    }
  }

  private acknowledgeAlert(alert: N_cStph.alarmInfo) {
    // 实现应答报警逻辑
    // 记录应答人，应答时间
    const data: Array<ifs.I_fv[]> = [
      [
        {
          field: 'respondent',
          value: Tsrv.getUserID()
        } as ifs.I_fv,
        {
          field: 'response_time',
          value: Tsrv.utils.toDateString(new Date())
        } as ifs.I_fv,
        {
          field: 'id',
          value: alert.alarmRowID
        } as ifs.I_fv,
        {
          field: 'is_respond',
          value: 1
        } as ifs.I_fv
      ]
    ];
    this.GT_command.modifyData('alarm_query', 'id', data).then(success => {
      if (success) {
        this.$Message.success('应答成功');
      }
    });
  }

  private resetAlert(alert: N_cStph.alarmInfo) {
    // 实现复位报警逻辑
    // 查看该报警是否应答，如果未应答，则复位并应答，如果已应答，则只复位
    this.GT_command.loadFilterList(['is_respond'], 'alarm_query', {
      id: { $in: [alert.alarmRowID] }
    }).then(res => {
      // 记录报警解除时间，主页不再提示该报警
      const data: Array<ifs.I_fv[]> = [
        [
          {
            field: 'release_time',
            value: Tsrv.utils.toDateString(new Date())
          } as ifs.I_fv,
          {
            field: 'id',
            value: alert.alarmRowID
          } as ifs.I_fv,
          {
            field: 'is_release',
            value: 1
          } as ifs.I_fv
        ]
      ];
      if (res.length > 0) {
        const isRespond = res[0].is_respond;
        if (isRespond === 0) {
          // 未应答，复位并应答
          const arr = [
            {
              field: 'respondent',
              value: Tsrv.getUserID()
            } as ifs.I_fv,
            {
              field: 'response_time',
              value: Tsrv.utils.toDateString(new Date())
            } as ifs.I_fv,
            {
              field: 'is_respond',
              value: 1
            } as ifs.I_fv
          ];
          data[0].push(...arr);
        }
      }

      this.GT_command.modifyData('alarm_query', 'id', data).then(success => {
        if (success) {
          this.$Message.success('复位成功');
          this.GT_command.alarmInfo = this.GT_command.alarmInfo.filter(
            info => info.alarmRowID !== alert.alarmRowID
          );
          // 主页不再显示该条报警信息
          this.lineHeaderInfo.forEach(item => {
            if (item.column.key === 'alert') {
              item.cases = item.cases.filter(
                it => it.alarmRowID !== alert.alarmRowID
              );
            }
          });

          // 该报警点位重置为0
          const d = [{ ecDetCode: alert.alarmCode, value: 'false' }];
          Tsrv.writePlcData(d);

          // 如果报警是某个槽报警,则复位报警时将该槽状态置为正常,并且判断是否还有挂组在其中进行加工
          const result = this.matchAlarmSlot([alert]);
          if (!Tsrv.noValue(result)) {
            // this.lineConfig.tanks.forEach(tank => {
            for (const tank of this.lineConfig.tanks) {
              if (result.includes(tank.id)) {
                if (
                  typeof tank.params.isClose !== 'undefined' &&
                  tank.params.isClose
                ) {
                  tank.status = 'closed';
                  continue;
                }
                // 然后处理工作状态
                if (tank.params.hangGroupID.value !== 0 && tank.id < 28) {
                  tank.status = 'working';
                }
                // 最后默认除缓存位外空闲状态
                else if (tank.id < 28) {
                  tank.status = 'idle';
                }
                if (
                  typeof tank.params.isClose !== 'undefined' &&
                  tank.id >= 28 &&
                  !tank.params.isClose.value
                ) {
                  tank.status = 'cache';
                }
              }
            }
          }
        }
      });
    });
  }

  private jumpToDeviceControl() {
    // 实现跳转设备控制逻辑
    if (Tsrv.noValue(this.selectedAlert.equipFunName)) {
      this.$Message.error('未找到设备功能');
      return;
    }
    this.$store
      .dispatch('getLayoutConfigAsync', {
        funid: null,
        field: this.selectedAlert.equipFunName,
        type: 'custom'
      })
      .then((res: any) => {
        if (res) {
          this.addTabFunc(this.selectedAlert.equipFunName);
        }
      });
  }

  private handleUpdateTank(obj: {
    field: string;
    value: number;
    tankID: number;
  }) {
    const { field, value, tankID } = obj;
    this.lineConfig.tanks.forEach(tank => {
      if (tank.id === tankID) {
        tank.params[field].value = value;
      }
    });
  }
}
</script>
<style lang="scss" scoped>
.production-overview {
  height: 100%;
  width: 100%;
  position: relative;
}
.init-container {
  // transform: scale(0.75);
  // transform-origin: 0 0;
  // width: 133.33%;
  // height: 133.33%;
  .header {
    height: 14%;
    display: grid;
    grid-template-columns: minmax(50px, 1fr) 2fr 2fr minmax(50px, 1fr);
    grid-template-rows: 1fr;
    column-gap: 5px;
    padding: 10px;

    .info-column {
      width: 100%;
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: flex-start;
      border: 1px solid #eee;
      border-radius: 5px;
      box-shadow: 2px 4px 2px -2px var(--globalSearch-input-bg-color),
        -2px -4px 15px -2px var(--globalSearch-input-bg-color);
      .info-title {
        width: 100%;
        // height: 20px;
        font-size: 14px;
        font-weight: 600;
        background: #e0e9f3;
        padding: 10px 0 10px 15px;
      }
      .info-content {
        width: 100%;
        height: 100%;
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 4px;
        background-color: #f0f2f5;
        .info-content-item {
          width: 100%;
          text-align: center;
          padding-top: 5px;
          background-color: #fff;
          display: flex;
          justify-content: center;
          align-items: center;
          .info-content-item-title {
            height: 100%;
            font-weight: 500;
            line-height: 22px;
            margin-right: 10px;
          }
          .info-content-item-value {
            width: 100%;
            height: 100%;
            line-height: 22px;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
          }
        }
      }
      .task-info {
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: space-between;
        align-content: center;
        .task-info-item {
          width: 100%;
          height: 100%;
          text-align: center;
          .task-info-item-title {
            height: 50%;
            box-shadow: #c1f0ef 1px 1px 1px 1px;
            display: flex;
            justify-content: center;

            align-items: center;
          }
          .task-info-item-value {
            height: 50%;
            box-shadow: #c1f0ef 1px 1px 1px 1px;
            display: flex;
            justify-content: center;
            align-items: center;
          }
        }
      }
    }
    .alert-column {
      max-width: 42vw;
      overflow-x: auto;
      height: 100%;

      .alert-title {
        width: 100%;
        font-size: 14px;
        font-weight: 600;
        background: #e0e9f3;
        padding: 9px 15px 9px 15px;
        // display: flex;
        // justify-content: space-between;
        // align-content: center;
      }
      .alert-info {
        width: 100%;
        height: 60%;
        overflow-x: auto;
        white-space: nowrap;
        border: 1px solid #eee;
        &::-webkit-scrollbar {
          // width: 3px;
          height: 6px;
          background: #f5f5f5;
          border-radius: 6px;
        }

        &::-webkit-scrollbar-track-piece {
          background: #fff;
          border-radius: 6px;
        }

        &::-webkit-scrollbar-thumb {
          background: #b1b1b1;
          border-radius: 6px;
        }
        .alert-content {
          display: inline-block;
          min-width: 100%;
          height: 90%;
          .alert-info-item {
            // display: inline-block; /* 使每个项目成为行内块元素 */
            width: 250px; /* 每个项目的宽度 */
            height: 100%;
            line-height: 3;
            margin-right: 10px; /* 每个项目之间的间距 */
            text-align: center; /* 文本居中 */
            border: 2px solid red; /* 增加边框宽度 */
            background-color: #ffcccc;
            color: darkred; /* 调整文本颜色以与背景形成对比 */
            font-size: 16px;
            font-weight: bold;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(255, 0, 0, 0.5); /* 添加红色阴影 */
            animation: blink-border 1s infinite; /* 应用边框闪烁动画 */
            position: relative;
            cursor: context-menu;
            display: inline-block;
            // justify-content: center;
            align-items: center;
          }
        }
      }
    }
  }
  .main {
    height: 54%;
    overflow: hidden;
  }
  .std-border {
    border: 1px solid #eee;
    border-radius: 5px;
    box-shadow: 2px 4px 2px -2px var(--globalSearch-input-bg-color),
      -2px -4px 15px -2px var(--globalSearch-input-bg-color);
  }
}
.modal-content {
  height: 100%;
  display: grid;
  grid-template-columns: 1fr 1.5fr;
  column-gap: 10px;
  .modal-left {
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;
    align-items: center;
  }
  .modal-right {
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;
  }
}

@keyframes blink-border {
  0%,
  100% {
    border-color: red; /* 起始和结束状态为红色边框 */
    box-shadow: 0 0 10px rgba(255, 0, 0, 0.5); /* 起始和结束状态的阴影 */
  }
  50% {
    border-color: darkred; /* 中间状态为深红色边框 */
    box-shadow: 0 0 20px rgba(139, 0, 0, 0.7); /* 中间状态的更强阴影 */
  }
}
@keyframes blink {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

.blink-text {
  animation: blink 1s infinite;
  color: #ffad33;
}
</style>
